package com.cqupt.common.log.aop;


import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.servlet.http.HttpServletRequest;

import com.cqupt.common.log.annotation.OperationLog;
import com.cqupt.mapper.LoginlogsMapper;
import com.cqupt.pojo.Loginlogs;
import com.cqupt.pojo.OperationLogEntity;
import com.cqupt.pojo.ResponseMessage;
import com.cqupt.pojo.User;
import com.cqupt.service.LogService;
import org.apache.log4j.Logger;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;


@Aspect
@Component
public class LogAopAction {

    //注入Service用于把日志保存数据库
    @Autowired
    private LogService systemLogService;
    // 时间线程
    ThreadLocal<Long> time = new ThreadLocal<Long>();
    private static final Logger logger = Logger.getLogger(OperationLog.class);
    //用于生成操作日志的唯一标识，用于业务流程审计日志调用
    public static ThreadLocal<String> tag = new ThreadLocal<String>();

    public Integer id = null;
    public static User user = new User();
    public static String username;

    @Autowired
    LoginlogsMapper loginlogsMapper;

    @Autowired
    HttpServletRequest request;


    public static User getUser(User u){
        user = u;
        return user;
    }

    public static String getUsername(String un){
        username = un;
        return username;
    }

    /**
     * 自定义切入点
     */
    @Pointcut("@annotation(com.cqupt.common.log.annotation.OperationLog)")
    public  void controllerAspect() {
        System.out.println("我是一个切入点");
    }
    /**
     * 自定义切入点
     */
    @Pointcut("execution(* com.cqupt.service.UserService.login(..))")
    public void loginCell(){
    }
    /**
     * 自定义切入点
     */
    @Pointcut("execution(* com.cqupt.service.UserService.logout(..))")
    public void logoutCell(){
    }

    /**
     * 环绕方法
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("loginCell()")
    public Object recordLogs(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        handle(joinPoint);
        return result;
    }

    /**
     * 环绕方法
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @Around("logoutCell()")
    public Object recordLogs2(ProceedingJoinPoint joinPoint) throws Throwable {
        Object result = joinPoint.proceed();
        handle2(joinPoint);
        return result;
    }

    /**
     * 处理
     * @param joinPoint
     * @throws NoSuchMethodException
     */
    private void handle(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        Date date = new Date();

        Loginlogs loginlogs ;
        if (user.getFlag() == 1)
            loginlogs = new Loginlogs(date,"信息","登录",user.getUsername(),"0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())?"127.0.0.1":request.getRemoteAddr(),"成功","");
        else if (user.getFlag() == 2)
            loginlogs = new Loginlogs(date,"警告","登录",user.getUsername(),"0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())?"127.0.0.1":request.getRemoteAddr(),"失败","用户名不存在");
        else if (user.getFlag() == 3)
            loginlogs = new Loginlogs(date,"警告","登录",user.getUsername(),"0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())?"127.0.0.1":request.getRemoteAddr(),"失败","密码错误");
        else
            loginlogs = new Loginlogs(date,"警告","登录",user.getUsername(),"0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())?"127.0.0.1":request.getRemoteAddr(),"失败","用户名或密码错误");
        loginlogsMapper.addLoginlogs(loginlogs);
    }

    /**
     * 处理
     * @param joinPoint
     * @throws NoSuchMethodException
     */
    private void handle2(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        Date date = new Date();
        Loginlogs loginlogs = new Loginlogs(date,"信息","退出",username,"0:0:0:0:0:0:0:1".equals(request.getRemoteAddr())?"127.0.0.1":request.getRemoteAddr(),"成功","");
        loginlogsMapper.addLoginlogs(loginlogs);
    }
    /**
     * 在所有标注@Log的地方切入
     * @param joinPoint
     */
    @Before("controllerAspect()")
    public void beforeExec(JoinPoint joinPoint) {
        time.set(System.currentTimeMillis());
        info(joinPoint);
        //设置日志记录的唯一标识号
        tag.set(UUID.randomUUID().toString());
    }

    /**
     * 后最方法
     * @param joinPoint
     */
    @After("controllerAspect()")
    public void afterExec(JoinPoint joinPoint) {
        MethodSignature ms = (MethodSignature) joinPoint.getSignature();
        Method method = ms.getMethod();
        logger.debug("标记为" + tag.get() + "的方法" + method.getName()
                + "运行消耗" + (System.currentTimeMillis() - time.get()) + "ms");
    }

    /**
     * 在执行目标方法的过程中，会执行这个方法，可以在这里实现日志的记录
     * @param pjp
     * @return
     * @throws Throwable
     */
    @Around("controllerAspect()")
    public Object aroundExec(ProceedingJoinPoint pjp) throws Throwable {
        Object ret = pjp.proceed();
        String error = ((ResponseMessage)ret).getErrorCode();
        String desc = (String) ((ResponseMessage)ret).getContent().get("log_description");
        String objectName = (String) ((ResponseMessage)ret).getContent().get("log_objectName");
        boolean flag = ((ResponseMessage)ret).isStatus();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        try {
            Object[] orgs = pjp.getArgs();
            //for (int i = 0; i < orgs.length; i++) {
            //    System.out.println(orgs[i]);
            //}
            OperationLogEntity valueReturn = null;

            for (int i = 0; i < orgs.length; i++) {
                if(orgs[i] instanceof OperationLogEntity){
                    valueReturn = (OperationLogEntity) orgs[i];
                }
            }

            if(valueReturn==null){
                valueReturn =  new OperationLogEntity();
            }
            String logSwitch = (String) request.getSession().getAttribute("logSwitch");
            try{if(valueReturn != null && request != null && logSwitch.equals("true")){
                MethodSignature ms = (MethodSignature) pjp.getSignature();
                Method method = ms.getMethod();
                //获取注解的操作日志信息
                OperationLog log = method.getAnnotation(OperationLog.class);
                String level = log.level();
                String modules = log.object();
                String operationType = log.operationType();
                //HashMap requestMap = (HashMap) analyseCallbackRequest(request);
                String userName = (String) request.getSession().getAttribute("username");
                //System.out.println("用户名："+userName);
                if (flag == true){
                    valueReturn.setDescription("" + desc);
                    valueReturn.setResult("成功");
                }else{
                    valueReturn.setDescription("" + error);
                    valueReturn.setResult("失败");
                }
                valueReturn.setUserName(userName);
                valueReturn.setLevel(level);
                valueReturn.setOperObject(modules);
                Date date = new Date();
                SimpleDateFormat dateFormat= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                valueReturn.setOperationTime(dateFormat.format(date));
                valueReturn.setOperObjectType(operationType);
                valueReturn.setDuration((System.currentTimeMillis() - time.get()) + "毫秒");
                valueReturn.setOperObjectName(objectName);

                //保存操作日志
                systemLogService.saveLog(valueReturn);
            }else{
                logger.info("不记录日志信息");
            }}catch (NullPointerException e){
                e.getMessage();
            }
            //保存操作结果
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }

    //记录异常日志
    //@AfterThrowing(pointcut = "controllerAspect()",throwing="e")
    //public  void doAfterThrowing(JoinPoint joinPoint, Throwable e) {
    //    try {
    //        info(joinPoint);
    //        Object[] orgs = joinPoint.getArgs();
    //        SystemLog valueReturn = null;
    //        for (int i = 0; i < orgs.length; i++) {
    //            if(orgs[i] instanceof SystemLog){
    //                valueReturn = (SystemLog) orgs[i];
    //            }
    //        }
    //        if(valueReturn==null){
    //            valueReturn =  new SystemLog();
    //        }
    //        if(valueReturn!=null&&request!=null){
    //            MethodSignature ms = (MethodSignature) joinPoint.getSignature();
    //            Method method = ms.getMethod();
    //            XXXOperateLog log = method.getAnnotation(XXXOperateLog.class);
    //            String businessType = log.bussType();
    //            String businessDesc = log.bussTypeDesc();
    //            if(businessType.equals(""))
    //            {
    //                Object objBusinessType = ServletUtils.getParametersToHashMap(request).get("business_type");
    //                businessType = objBusinessType == null ? "" : objBusinessType.toString();
    //                businessDesc = XXXSysConstant.BUSINESS_TYPE.getName(businessType);
    //            }
    //            valueReturn.setBussType(XXXSysConstant.BUSINESS_TYPE.getNumber(businessType));
    //            valueReturn.setBussTypeDesc(businessDesc);
    //            valueReturn.setMoudleCode(log.moudleCode());
    //            valueReturn.setMoudleName(log.moudleName());
    //            valueReturn.setOperateType(log.operateType());
    //            valueReturn.setOperateTypeDesc(log.operateTypeDesc());
    //            valueReturn.setInputUserId(((UserContext)WebUtils.getSessionAttribute(request, "XXXuserContext")).getSysUser().getId());
    //            valueReturn.setOperateResult(XXXSysConstant.YesOrNo.NO);
    //            String errMes = e.getMessage();
    //            if(errMes!=null && errMes.length()>800){
    //                errMes = errMes.substring(0, 800);
    //            }
    //            valueReturn.setErrorMessage(errMes);
    //            valueReturn.setRequestIp(getRemoteHost(request));
    //            valueReturn.setRequestUrl(request.getRequestURI());
    //            valueReturn.setServerIp(request.getLocalAddr());
    //            valueReturn.setUids(tag.get());
    //            systemLogService.saveSystemLog(valueReturn);
    //        }else{
    //            logger.info("不记录日志信息");
    //        }
    //    } catch (Exception e1) {
    //        e1.printStackTrace();
    //    }
    //}

    /**
     * 参数信息
     * @param joinPoint
     */
    private void info(JoinPoint joinPoint) {
        logger.debug("--------------------------------------------------");
        logger.debug("King:\t" + joinPoint.getKind());
        logger.debug("Target:\t" + joinPoint.getTarget().toString());
        Object[] os = joinPoint.getArgs();
        logger.debug("Args:");
        for (int i = 0; i < os.length; i++) {
            logger.debug("\t==>参数[" + i + "]:\t" + os[i].toString());
        }
        logger.debug("Signature:\t" + joinPoint.getSignature());
        logger.debug("SourceLocation:\t" + joinPoint.getSourceLocation());
        logger.debug("StaticPart:\t" + joinPoint.getStaticPart());
        logger.debug("--------------------------------------------------");
    }
    /**
     * 获取远程客户端Ip
     * @param request
     * @return
     */
    private  String getRemoteHost(javax.servlet.http.HttpServletRequest request){
        String ip = request.getHeader("x-forwarded-for");
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)){
            ip = request.getRemoteAddr();
        }
        return ip.equals("0:0:0:0:0:0:0:1")?"127.0.0.1":ip;
    }
    /**
     * 把request转为map
     *
     * @param request
     * @return
     */
    private Map<String, Object> getParameterMap(HttpServletRequest request) {
        // 参数Map
        Map<?, ?> properties = request.getParameterMap();
        // 返回值Map
        Map<String, Object> returnMap = new HashMap<String, Object>();
        Iterator<?> entries = properties.entrySet().iterator();

        Map.Entry<String, Object> entry;
        String name = "";
        String value = "";
        Object valueObj =null;
        while (entries.hasNext()) {
            entry = (Map.Entry<String, Object>) entries.next();
            name = (String) entry.getKey();
            valueObj = entry.getValue();
            if (null == valueObj) {
                value = "";
            } else if (valueObj instanceof String[]) {
                String[] values = (String[]) valueObj;
                for (int i = 0; i < values.length; i++) {
                    value = values[i] + ",";
                }
                value = value.substring(0, value.length() - 1);
            } else {
                value = valueObj.toString();
            }
            returnMap.put(name, value);
        }
        return returnMap;
    }

}
